﻿using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Digitalmes.Infrastructure.Common;

/// <summary>
/// CMD 操作
/// </summary>
public static class Cmd
{
    /// <summary>
    /// 执行 cmd 命令。
    /// </summary>
    /// <param name="arguments">要执行命令的参数。</param>
    public static async Task ExecCMD(string arguments)
    {
        string processName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd.exe" : "/bin/bash";
        await Exec(processName, arguments);
    }

    /// <summary>
    /// 执行命令，或调用shell脚本，或启用应用程序。
    /// </summary>
    /// <param name="fileName">要启动的文件名称。</param>
    /// <param name="arguments">启动时的参数，默认为 ("")。</param>
    public static async Task Exec(string fileName, string arguments = "", CancellationToken cancellationToken = default) 
    {
        ProcessStartInfo psi = new()
        {
            FileName = fileName,
            Arguments = arguments,
            UseShellExecute = false, // 是否使用操作系统shell启动。如果 false，则直接从创建的进程中运行可执行文件；如果 true，则通过操作系统的 shell 执行。若要重定向输入/输出流时需要设为 false。
            RedirectStandardInput = true, // 接受来自调用程序的输入信息，允许程序向cmd发送命令，例如，启动cmd后，后续还可以分多步敲入命令。
            RedirectStandardOutput = true, // 将标准输出流重定向，允许程序捕获cmd的输出。
            RedirectStandardError = true, // 将错误输出流重定向，允许程序捕获cmd的错误信息。
            CreateNoWindow = true, // 启动进程时不创建新窗口，使其在后台运行
        };

        using Process proc = new()
        {
            StartInfo = psi,
        };
        proc.Start();
        await proc.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
    }
}
